package com.dot.comm.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

//import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class HttpUtils {

    /**
     * 连接超时
     */
    private static int connectTimeOut = 5000;

    /**
     * 读取数据超时
     */
    private static int readTimeOut = 10000;

    /**
     * 超时处理时间
     */
    private final static int overTimeOut = 60000;

    /**
     * 请求编码
     */
    private static String requestEncoding = "utf-8";

    public static int getConnectTimeOut() {
        return HttpUtils.connectTimeOut;
    }

    public static int getReadTimeOut() {
        return HttpUtils.readTimeOut;
    }

    public static String getRequestEncoding() {
        return requestEncoding;
    }

    public static void setConnectTimeOut(int connectTimeOut) {
        HttpUtils.connectTimeOut = connectTimeOut;
    }

    public static void setReadTimeOut(int readTimeOut) {
        HttpUtils.readTimeOut = readTimeOut;
    }

    public static void setRequestEncoding(String requestEncoding) {
        HttpUtils.requestEncoding = requestEncoding;
    }


    /**
     * <pre>
     * 发送带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String doGet(String reqUrl, Map<String, ?> parameters) {
        String result = null;
        Future<?> future = null;
        String recvEncoding = requestEncoding;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doGet0(reqUrl, parameters, recvEncoding);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    private static String doGet0(String reqUrl, Map<?, ?> parameters, String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            StringBuffer params = new StringBuffer();
            for (Iterator<?> iter = parameters.entrySet().iterator(); iter.hasNext(); ) {
                Entry<?, ?> element = (Entry<?, ?>) iter.next();
                if (element.getValue() != null) {
                    params.append(element.getKey().toString());
                    params.append("=");
                    params.append(URLEncoder.encode(element.getValue().toString(),
                            HttpUtils.requestEncoding));
                    params.append("&");
                }
            }

            if (params.length() > 0) {
                params = params.deleteCharAt(params.length() - 1);
            }

            if (reqUrl.indexOf("?") != -1) {
                reqUrl += "&" + params;
            } else {
                reqUrl += "?" + params;
            }

            URL url = new URL(reqUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("GET");
            url_con.setConnectTimeout(HttpUtils.connectTimeOut);//（单位：毫秒）jdk
            url_con.setReadTimeout(HttpUtils.readTimeOut);//（单位：毫秒）jdk 1.5换成这个,读操作超时

            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in, recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer temp = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                temp.append(tempLine);
                temp.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = temp.toString();
            rd.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * <pre>
     * 发送不带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl HTTP请求URL
     * @return HTTP响应的字符串
     * @throws Exception
     */
    public static String doGet(String reqUrl, String recvEncoding) throws Exception {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doGet0(reqUrl, recvEncoding);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
            throw e;
        }
        return result;
    }

    private static String doGet0(String reqUrl, String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            StringBuffer params = new StringBuffer();
            String queryUrl = reqUrl;
            int paramIndex = reqUrl.indexOf("?");

            if (paramIndex > 0) {
                queryUrl = reqUrl.substring(0, paramIndex);
                String parameters = reqUrl.substring(paramIndex + 1, reqUrl.length());
                String[] paramArray = parameters.split("&");
                for (int i = 0; i < paramArray.length; i++) {
                    String string = paramArray[i];
                    int index = string.indexOf("=");
                    if (index > 0) {
                        String parameter = string.substring(0, index);
                        String value = string.substring(index + 1, string.length());
                        params.append(parameter);
                        params.append("=");
                        params.append(URLEncoder.encode(value, HttpUtils.requestEncoding));
                        params.append("&");
                    }
                }

                params = params.deleteCharAt(params.length() - 1);
            }

            URL url = new URL(queryUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("GET");
            url_con.setConnectTimeout(HttpUtils.connectTimeOut);//（单位：毫秒）jdk
            url_con.setReadTimeout(HttpUtils.readTimeOut);//（单位：毫秒）jdk 1.5换成这个,读操作超时
            url_con.setDoOutput(true);
            byte[] b = params.toString().getBytes();
            url_con.getOutputStream().write(b, 0, b.length);
            url_con.getOutputStream().flush();
            url_con.getOutputStream().close();
            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in, recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer temp = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                temp.append(tempLine);
                temp.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = temp.toString();
            rd.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * <pre>
     * 发送带参数的POST的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String doPost(String reqUrl, Map<?, ?> parameters, String recvEncoding) {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doPost0(reqUrl, parameters, recvEncoding);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    public static String doPost(String reqUrl, String json) {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doPost0(reqUrl, json);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    private static String doPost0(String reqUrl, String json) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(reqUrl);
        try {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(HttpUtils.connectTimeOut).build();
            httpPost.setConfig(requestConfig);
            ByteArrayEntity entityReq = new ByteArrayEntity(json.getBytes(), ContentType.APPLICATION_JSON);
//            entityReq.setContentEncoding("UTF-8");
            entityReq.setContentType("application/json");
            httpPost.setEntity(entityReq);
            HttpResponse response;
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String retStr = null;
            if (entity != null) {
                retStr = EntityUtils.toString(entity, "UTF-8");
            }
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
                System.out.println("Http post 请求异常：" + retStr);
            return retStr;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private static String doPost0(String reqUrl, Map<?, ?> parameters, String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            StringBuffer params = new StringBuffer();
            for (Iterator<?> iter = parameters.entrySet().iterator(); iter.hasNext(); ) {
                Entry<?, ?> element = (Entry<?, ?>) iter.next();
                if (element.getValue() != null) {
                    params.append(element.getKey().toString());
                    params.append("=");
                    params.append(URLEncoder.encode(element.getValue().toString(),
                            HttpUtils.requestEncoding));
                    params.append("&");
                }
            }

            if (params.length() > 0) {
                params = params.deleteCharAt(params.length() - 1);
            }
            // reqUrl += "?" + params;
            // System.out.println("reqUrl:" + reqUrl);
            URL url = new URL(reqUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("POST");
            url_con.setRequestProperty("accept", "*/*");
            url_con.setRequestProperty("connection", "Keep-Alive");
            url_con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            url_con.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
//            System.setProperty("sun.net.client.defaultConnectTimeout",
//                               String.valueOf(HttpUtils.connectTimeOut));// （单位：毫秒）jdk1.4换成这个,连接超时
//            System.setProperty("sun.net.client.defaultReadTimeout",
//                               String.valueOf(HttpUtils.readTimeOut)); // （单位：毫秒）jdk1.4换成这个,读操作超时
            url_con.setConnectTimeout(HttpUtils.connectTimeOut);//（单位：毫秒）jdk
//             1.5换成这个,连接超时
            url_con.setReadTimeout(HttpUtils.readTimeOut);//（单位：毫秒）jdk 1.5换成这个,读操作超时
            url_con.setDoOutput(true);
            url_con.setDoInput(true);
            byte[] b = params.toString().getBytes();
            url_con.getOutputStream().write(b, 0, b.length);
            url_con.getOutputStream().flush();
            url_con.getOutputStream().close();

            if (url_con.getResponseCode() == 200) {
                InputStream in = url_con.getInputStream();
                BufferedReader rd = new BufferedReader(new InputStreamReader(in, recvEncoding));
                String tempLine = rd.readLine();
                StringBuffer tempStr = new StringBuffer();
                String crlf = System.getProperty("line.separator");
                while (tempLine != null) {
                    tempStr.append(tempLine);
                    tempStr.append(crlf);
                    tempLine = rd.readLine();
                }
                responseContent = tempStr.toString();
                rd.close();
                in.close();
            } else {
                responseContent = "{\"code\":" + url_con.getResponseCode() + "}";
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    public static String doPostHttp(String reqUrl, Map<?, ?> headerParam, Map<?, ?> bodyParam) {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doPostHttp0(reqUrl, headerParam, bodyParam);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    /**
     * 发送json参数请求，添加了允许跨域
     *
     * @param reqUrl
     * @param headerParam
     * @param bodyParam
     * @return
     */
    public static String doPostJson(String reqUrl, Map<String, Object> bodyParam, Map<String, Object> headerParam) {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            if (headerParam == null) {
                headerParam = new HashMap<>();
            }
            headerParam.put("Content-Type", "application/json");
            headerParam.put("Accept", "*/*");
            Map<String, Object> finalHeaderParam = headerParam;
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doPostHttp0(reqUrl, finalHeaderParam, bodyParam);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    private static String doPostHttp0(String reqUrl, Map<?, ?> headerParam, Map<?, ?> bodyParam) {
        CloseableHttpClient httpclient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost(reqUrl);
        try {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(HttpUtils.connectTimeOut).build();
            httpPost.setConfig(requestConfig);
            for (Entry<?, ?> entry : headerParam.entrySet()) {
                httpPost.addHeader(entry.getKey().toString(), entry.getValue().toString());
            }
            String param = JSONObject.toJSONString(bodyParam);
            StringEntity entityReq = new StringEntity(param, "utf-8");//解决中文乱码问题
            entityReq.setContentEncoding("UTF-8");
            entityReq.setContentType("application/json");

            httpPost.setEntity(entityReq);
            HttpResponse response;
            response = httpclient.execute(httpPost);

            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                String retStr = "";
                if (entity != null) {
                    retStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("retStr:" + retStr);
                return retStr;
            }
            HttpEntity entity = response.getEntity();
            String retStr = "";
            if (entity != null) {
                retStr = EntityUtils.toString(entity, "UTF-8");
            }
            return retStr;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    public static String postXML(String urlStr, Map<String, String> paramMap) {
        try {
            URL url = new URL(urlStr);
            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");

            OutputStreamWriter out = new OutputStreamWriter(con
                    .getOutputStream());
            String xmlInfo = getXmlInfo(paramMap);
            out.write(new String(xmlInfo.getBytes("UTF-8")));
            out.flush();
            out.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(con
                    .getInputStream()));
            String line = "";
            String result = "";
            for (line = br.readLine(); line != null; line = br.readLine()) {
                result += line + "\n";
            }
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    private static String getXmlInfo(Map<String, String> paramMap) {
        if (paramMap != null && paramMap.size() > 0) {
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");

            for (String key : paramMap.keySet()) {
                sb.append("<" + key + ">").append(paramMap.get(key) + "</" + key + ">");
            }
            sb.append("</xml>");
            return sb.toString();
        }
        return null;
    }

//    public static byte[] getRequestPostBytes(HttpServletRequest request)
//            throws IOException {
//        int contentLength = request.getContentLength();
//        if (contentLength < 0) {
//            return null;
//        }
//        byte buffer[] = new byte[contentLength];
//        for (int i = 0; i < contentLength; ) {
//
//            int readlen = request.getInputStream().read(buffer, i,
//                    contentLength - i);
//            if (readlen == -1) {
//                break;
//            }
//            i += readlen;
//        }
//        return buffer;
//    }

//    public static String getRequestPostStr(HttpServletRequest request)
//            throws IOException {
//        byte buffer[] = getRequestPostBytes(request);
//        String charEncoding = request.getCharacterEncoding();
//        if (charEncoding == null) {
//            charEncoding = "UTF-8";
//        }
//        return new String(buffer, charEncoding);
//    }

    public static String doPostForm(String reqUrl, Map<?, ?> headerParam, Map<?, ?> bodyParam) {
        String result = null;
        Future<?> future = null;
        LongTimeHttpPool httpPool = LongTimeHttpPool.getInstance();
        try {
            future = httpPool.execute(new Callable<String>() {
                @Override
                public String call() {
                    return doPostForm0(reqUrl, headerParam, bodyParam);
                }
            });
            result = future.get(overTimeOut, TimeUnit.MILLISECONDS).toString();
        } catch (Exception e) {
            e.printStackTrace();
            future.cancel(true);
        }
        return result;
    }

    private static String doPostForm0(String reqUrl, Map<?, ?> headerParam, Map<?, ?> bodyParam) {
        CloseableHttpClient httpclient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost(reqUrl);
        try {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(HttpUtils.connectTimeOut).build();
            httpPost.setConfig(requestConfig);
            for (Entry<?, ?> entry : headerParam.entrySet()) {
                httpPost.addHeader(entry.getKey().toString(), entry.getValue().toString());
            }
            //声明List集合，封装表单中的参数
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            for (Entry<?, ?> entry : bodyParam.entrySet()) {
                httpPost.addHeader(entry.getKey().toString(), entry.getValue().toString());
                params.add(new BasicNameValuePair(entry.getKey().toString(), entry.getValue().toString()));
            }

            UrlEncodedFormEntity entityReq = new UrlEncodedFormEntity(params, "utf-8");//解决中文乱码问题
            entityReq.setContentEncoding("UTF-8");
            entityReq.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(entityReq);
            HttpResponse response;
            response = httpclient.execute(httpPost);

            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                String retStr = "";
                if (entity != null) {
                    retStr = EntityUtils.toString(entity, "UTF-8");
                }
                System.out.println("retStr:" + retStr);
                return retStr;
            }
            HttpEntity entity = response.getEntity();
            String retStr = "";
            if (entity != null) {
                retStr = EntityUtils.toString(entity, "UTF-8");
            }
            return retStr;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
